package com.silverhaze.diamond.client.utils.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * User: Babanin
 * Date: 16.04.11
 * Time: 11:46
 */
public abstract class BackgroundTask implements Runnable {
    private boolean canceled;
    private boolean forceFinished;

    private String description;
    private Future futureResult;
    private List<BackgroundTaskListener> listeners;

    public BackgroundTask() {
        this(null);

        canceled = false;
        forceFinished = false;
    }

    public BackgroundTask(String description) {
        this.canceled = false;
        this.description = description;
        this.listeners = new ArrayList<BackgroundTaskListener>();
    }

    public void onCancel() {
    }

    public void onFinish() {
    }

    @Override()
    @Deprecated()
    public void run() {
        try {
            execute();
        } catch (Exception e) {
            forceFinished = true;
            throw new RuntimeException(e);
        } finally {
            onFinish();
        }
    }

    public abstract void execute();

    public boolean isVisible() {
        return true;
    }

    public boolean isCancelable() {
        return true;
    }

    public Future getFutureResult() {
        return futureResult;
    }

    public void setFutureResult(Future futureResult) {
        this.futureResult = futureResult;
    }

    public void subscribe(BackgroundTaskListener listener) {
        if (listener != null && !listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    public void fireListeners() {
        try {
            Object taskResult = futureResult.get();

            for (BackgroundTaskListener listener : listeners) {
                listener.taskCompleted(taskResult);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    public void cancel() {
        if (getFutureResult().cancel(true)) {
            canceled = true;
            onCancel();
        }
    }

    public boolean isCanceled() {
        return canceled;
    }

    public boolean isForceFinished() {
        return forceFinished;
    }

    public void unsubscribe(BackgroundTaskListener listener) {
        if (listener != null) {
            listeners.remove(listener);
        }
    }

    public String getDescription() {
        return description;
    }
}
